
cd $directory


************************************************
*Set list of margins; becomes points on x axis
************************************************

global MARGLIST = "50 75 100 150 225 330 500 750 1000 1500 2250 3300 5000 7500 10000 15000 22500 33000 50000 75000 100000"
global MARGLISTPCT = ".0000001 .0000002 .0000005 .000001 .000002 .000005 .00001 .00002 .00005 .0001 .00015 .0002 .0003 .00045 .0007 .001"
global MARGLISTPCT2 = ".0000001 .0000002 .0000005 .000001 .000002 .000005 .00001 .00002 .00005 .0001 .0002 .0005 .001"

global LIST = "52201 69006 69106 " // M1GerusoEtAl correctedEconomist correctedSilver
 
************************************************
*Storage for Summary Statistics
************************************************

matrix define REC		=J(30, 10, .) 		//table of summary of reversal rates; columns are models, rows are critical margins of votes dropped from winner or gained by loser
matrix define RECPCT	=J(30, 10, .) 		//table of summary of reversal rates based on % margins; 	columns are models, rows are %critical margins of votes dropped from winner or gained by loser
matrix define REC1STATE		=J(30, 10, .) 		//1 state, replicates REC table of summary of reversal rates; columns are models, rows are critical margins of votes dropped from winner or gained by loser
matrix define REC2STATE		=J(30, 10, .) 		//2 states combined; table of summary of reversal rates; columns are models, rows are critical margins of votes dropped from winner or gained by loser
matrix define REC3STATE		=J(30, 10, .) 		//3 states combined; table of summary of reversal rates; columns are models, rows are critical margins of votes dropped from winner or gained by loser
matrix define RECPCT1STATE		=J(30, 10, .) 		//1 state, replicates REC table of summary of reversal rates; columns are models, rows are critical margins of votes dropped from winner or gained by loser
matrix define RECPCT2STATE		=J(30, 10, .) 		//2 states combined; table of summary of reversal rates; columns are models, rows are critical margins of votes dropped from winner or gained by loser
matrix define RECPCT3STATE		=J(30, 10, .) 		//3 states combined; table of summary of reversal rates; columns are models, rows are critical margins of votes dropped from winner or gained by loser
matrix define RECDECWIN	=J(30, 10, .) 		//table of summary of reversal rates; condl on D EC WINS
matrix define RECRECWIN	=J(30, 10, .) 		//table of summary of reversal rates; condl on D EC WINS
matrix define RPV		=J(30, 10, .) 		//table of summary of NPV reversal rates;
matrix define RPVPCT	=J(30, 10, .) 		//table of summary of NPV reversal rates; in % margins (pp)
matrix define RECPCT1STATE2		=J(30, 10, .) 		// like RECPCTXSTATE, but uses MARGLISTPCT2 
matrix define RECPCT2STATE2		=J(30, 10, .) 		// like RECPCTXSTATE, but uses MARGLISTPCT2 
matrix define RECPCT3STATE2		=J(30, 10, .) 		// like RECPCTXSTATE, but uses MARGLISTPCT2 



************************************************
*Outer loop - open datasets
************************************************

global LOOP = 2

foreach file in $LIST{

	use "working_data`c(dirsep)'min_vote_reversal_upto3_`file'.dta", clear

************************************************
*stats and vars
************************************************

//count states 
local error=0
local counter=1
while `error' != 111 {
	qui cap d total_ev_`counter'
	local error=_rc
	local counter=`counter'+1
}
global STATECOUNT = `counter'-2 
di "$STATECOUNT"
local state_count = `counter'-2 

	qui egen pvotes = rowtotal(twoPartyVotes_*)
	qui egen rvotes = rowtotal(rvotes_*)
	qui gen pvshare = rvotes/pvotes
	qui egen ev_denominator = rowtotal(total_ev_*)
	qui gen margin_share = abs(0.5-pvshare)*2
	qui gen margin_votes = margin_share*pvotes
	
	qui gen dwin = (ev_denominator-revn_total)/ev_denominator > 0.5
	
	
	//This loop identifies which states can flip election on their own (swing==1) and if so, 
	//how many votes must be dropped to do it(vmargin==X)
	forvalues i = 1(1)`state_count'{
		ren vmargin_`i' old_vmargin_`i'
		qui gen vmargin_`i' =  twoPartyVotes_`i'*abs(0.5- R_pvShare_`i')*2 //multiply by 2 to get the number of votes that separate candidates ((1-Rshare)-Rshare) = 1-2rshare
		qui replace cf_revn_total = revn_total //reset each loop
		qui replace cf_rwin = rwin //reset each loop
		qui replace cf_revn_total = cf_revn_total - total_ev_`i' if rwin_`i' == 1 //substract state to ECV count if R won the sim
		qui replace cf_revn_total = cf_revn_total + total_ev_`i' if rwin_`i' == 0 //add state from ECV count if R lost the sim
		qui replace cf_rwin =  cf_revn_total/ev_denominator > 0.5 //did R win in the counterfactual flip of the state?
		qui gen swing_`i' = cf_rwin != rwin //did the outcome of the election change? 
		//^this allows a change from not a tie to a tie or vice versa to count as a change
		qui replace vmargin_`i' = . if swing_`i' == 0 //keep vmargin blank if the state can't flip the election alone
		label var vmargin_`i' "The margin in vote counts in state `i'"
		
		//Levels: cylce through marglist to get probability of flips at each margin
		foreach marg in $MARGLIST{
			qui gen swing`marg'_`i' = swing_`i'==1 & vmargin_`i'<`marg'
			label var swing`marg'_`i' "Binary: is vmargin_`i' less than `marg'"
		}
		//PP: cylce through % marglist to get probability of flips at each margin
		foreach marg in $MARGLISTPCT{
			local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
			qui gen swingpct`labelmarg'_`i' = swing_`i'==1 & (vmargin_`i'/pvote)<`marg'
			label var swingpct`labelmarg'_`i' "Binary: is vmargin_`i' less than `marg' expressed as pct of turnout"
		}	
		foreach marg in $MARGLISTPCT2{
			local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
			qui gen swingpct`labelmarg'2_`i' = swing_`i'==1 & (vmargin_`i'/pvote)<`marg'
			label var swingpct`labelmarg'2_`i' "Binary: is vmargin_`i' less than `marg' expressed as pct of turnout"
		}	
		
}
	
	
	gen closest_flippable_state=.
	qui egen min_vmargin = rowmin(vmargin_*) 
	label var min_vmargin "minimum votes needed to flip closest state"
	qui gen tipping_state = .
	forvalues i = 1(1)`state_count'{
		qui replace closest_flippable_state = `i' if min_vmargin == vmargin_`i'
	}

	//the calculation of min_vmargin assumes *exactly* 2 states are flipped
	//But here allow that if 1 state flipping takes less votes and flips the election, we want the two state margin lowered
	gen min_vmarginOR1 = min_vmargin1
	gen min_vmarginOR2 = min_vmargin2
	replace min_vmarginOR2 = min_vmargin1 if min_vmargin1<min_vmargin2
	gen min_vmarginOR3 = min_vmargin3
	replace min_vmarginOR3 = min_vmargin2 if min_vmargin2<min_vmargin3
	replace min_vmarginOR3 = min_vmargin1 if min_vmargin1<min_vmarginOR3
	egen swingers = rowtotal(swing_*)
	
	//EC Reversals
	foreach marg in $MARGLIST{
		qui egen swing`marg' = rowtotal(swing`marg'_*)
		qui replace swing`marg' = 0 if swing`marg' == .
		qui gen Reversed`marg' = (swing`marg'>0 & swing`marg'<51)
		qui replace Reversed`marg' = 0 if swing`marg' == .
		label var Reversed`marg' "EC reversed by at least one state dropping `marg' votes"
		
		forvalues statecount=1(1)3{
			qui gen Reversed`statecount'_`marg' = (min_vmarginOR`statecount' <`marg')
			qui replace Reversed`statecount'_`marg' = 0 if min_vmarginOR`statecount' ==.
		}
	}
	*drop swing`marg'_*

	//PP EC Reversals
	foreach marg in $MARGLISTPCT2{
		local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
		di `labelmarg'
		qui egen swingpct`labelmarg'2 = rowtotal(swingpct`labelmarg'2_*)
		qui replace swingpct`labelmarg'2 = 0 if swingpct`labelmarg'2 == .
		qui gen Reversedpct`labelmarg'2 = (swingpct`labelmarg'2>0 & swingpct`labelmarg'2<51)
		qui replace Reversedpct`labelmarg'2 = 0 if swingpct`labelmarg'2 == .
		label var Reversedpct`labelmarg'2 "EC reversed by at least one state dropping `marg' pp votes"

		forvalues statecount=1(1)3{
			qui gen Reversedpct`statecount'2_`labelmarg' = ((min_vmarginOR`statecount'/pvotes) <`marg')
			qui replace Reversedpct`statecount'2_`labelmarg' = 0 if min_vmarginOR`statecount' ==.
		}
		
	}
	
	//PP EC Reversals
	foreach marg in $MARGLISTPCT{
		local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
		di `labelmarg'
		qui egen swingpct`labelmarg' = rowtotal(swingpct`labelmarg'_*)
		qui replace swingpct`labelmarg' = 0 if swingpct`labelmarg' == .
		qui gen Reversedpct`labelmarg' = (swingpct`labelmarg'>0 & swingpct`labelmarg'<51)
		qui replace Reversedpct`labelmarg' = 0 if swingpct`labelmarg' == .
		label var Reversedpct`labelmarg' "EC reversed by at least one state dropping `marg' pp votes"

		forvalues statecount=1(1)3{
			qui gen Reversedpct`statecount'_`labelmarg' = ((min_vmarginOR`statecount'/pvotes) <`marg')
			qui replace Reversedpct`statecount'_`labelmarg' = 0 if min_vmarginOR`statecount' ==.
		}
		
	}
	
	
	
	//NPV Reversals
	foreach marg in $MARGLIST{
		qui gen PVswing`marg'=0
		qui replace PVswing`marg' = 1 if margin_votes<`marg'
		
	}	

	//PP NPV Reversals
	foreach marg in $MARGLISTPCT{
		local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
		qui gen PVswingpct`labelmarg'=0
		qui replace PVswingpct`labelmarg' = 1 if (margin_votes/pvotes)<`marg'
	}	
	
	qui replace swingers = 0 if swingers == .
	qui gen ec_margin = min_vmargin
	qui gen pv_margin = margin_votes
	
	qui gen zero = swingers == 0
	label var swingers "number of states that could swing election"
	
	************************************************
	*Data for  figures
	************************************************
	local col = $LOOP
	di `col'
	*di `file'

	matrix REC[1, `col'] 		= `file'
	matrix RECPCT[1, `col'] 	= `file'
	matrix RECDECWIN[1, `col'] 	= `file'
	matrix RECRECWIN[1, `col'] 	= `file'
	matrix RPV[1, `col'] 		= `file'
	matrix RPVPCT[1, `col']		= `file'	
	matrix RECPCT2STATE2[1, `col']		= `file'
	matrix RECPCT3STATE2[1, `col']		= `file'
	
	local row = 2 //place marglist in rows starting at 2
	//stores fraction of sims reversed by indicated margin
	foreach marg in $MARGLIST{

		matrix REC[`row',1] = `marg'
		matrix RECDECWIN[`row',1] = `marg'
		matrix RECRECWIN[`row',1] = `marg'
		matrix RPV[`row',1] = `marg'
		
		qui summ Reversed`marg'
		matrix REC[`row',`col'] = r(mean)
		qui summ Reversed`marg' if dwin==1
		matrix RECDECWIN[`row',`col'] = r(mean)
		qui summ Reversed`marg' if rwin==1
		matrix RECRECWIN[`row',`col'] = r(mean)
		
		qui summ PVswing`marg'
		matrix RPV[`row',`col'] = r(mean)		
	
		//allocating min votes across 1, 2, 3 states
		forvalues statecount=1(1)3{
			matrix REC`statecount'STATE[`row',1] = `marg'
			qui summ Reversed`statecount'_`marg'
			matrix REC`statecount'STATE[`row',`col'] = r(mean)
		}
		
		local row = `row'+1
	}



	local row = 2 //place marglist in rows starting at 2
	//stores fraction of sims reversed by indicated margin
	foreach marg in $MARGLISTPCT{
		local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
		matrix RECPCT[`row',1] = `marg'
		matrix RPVPCT[`row',1] = `marg'
		
		qui summ Reversedpct`labelmarg'
		matrix RECPCT[`row',`col'] = r(mean)
		qui summ PVswingpct`labelmarg'
		matrix RPVPCT[`row',`col'] = r(mean)		
		
		//allocating min votes across 1, 2, 3 states
		forvalues statecount=1(1)3{
			matrix RECPCT`statecount'STATE[`row',1] = `marg'
			qui summ Reversedpct`statecount'_`labelmarg'
			matrix RECPCT`statecount'STATE[`row',`col'] = r(mean)
		}
		
		local row = `row'+1
	}

	local row = 2 //place marglist in rows starting at 2
	//stores fraction of sims reversed by indicated margin
		foreach marg in $MARGLISTPCT2{
		local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
		
		//allocating min votes across 1, 2, 3 states
		forvalues statecount=1(1)3{
			matrix RECPCT`statecount'STATE2[`row',1] = `marg'
			qui summ Reversedpct`statecount'2_`labelmarg'
			matrix RECPCT`statecount'STATE2[`row',`col'] = r(mean)
		}
		
		local row = `row'+1
	}
	
	
************************************************
*Outer loop - open datasets
************************************************
	
global LOOP = $LOOP +1		
di "$LOOP"
	
}

global ENDLOOP = $LOOP

cap drop REC*
svmat REC
svmat REC1STATE
svmat REC2STATE
svmat REC3STATE
svmat RECPCT1STATE
svmat RECPCT2STATE
svmat RECPCT3STATE
svmat RECPCT2STATE2
svmat RECPCT3STATE2
cap drop RPV*
svmat RPV


forvalues i=2(1)4{

	local file = REC`i' in 1
	di `file'
	

	if `file'==52201{
		local simlabel = "Geruso et al., 2022"
		local filelabel = "BGeruso" //52201
		local range = .0000001
	}
	if `file'==69006{
		local simlabel = "Gelman et al., 2020"
		local filelabel = "AGelman" //69006
		local range = .000001
	}
	if `file'==69106{
		local simlabel = "Silver et al., 2020"
		local filelabel = "CSilver" //69106
		local range = .000001
	}
	

qui summ REC`i' in 4 
local ecpostY = r(mean) + .0005
qui summ REC1 in 4
local ecpostX = r(mean)

qui summ RPV`i' in 15 
local npvpostY = r(mean) - .0005
qui summ REC1 in 15
local npvpostX = r(mean)


local labsize = "med"
local legsize = "small"
twoway ///
	(connected RECPCT1STATE`i' RECPCT1STATE1 in 2/100 if RECPCT1STATE1>0.00001 , lw(thin)   lcolor(black) ms(none) ) ///
	(connected RECPCT2STATE`i' RECPCT1STATE1 in 2/100 if RECPCT1STATE1>0.00001 , lw(medthick) lcolor(black) ms(none) ) ///
	(connected RECPCT3STATE`i' RECPCT1STATE1 in 2/100 if RECPCT1STATE1>0.00001 , lw(thick)  lcolor(black) ms(none) ) ///
	, ///
	aspect(1) ///
	xtitle("Margin (Percent of Turnout)", size(`labsize')) ///
	ytitle("Probability Margin Is Pivotal", size(`labsize')) ///
	ysc(log r(0.01 0.45)) ///
	xsc(log r(.000025 .001)) ///
	ylab( 0.02500 "2.5%" 0.0500 "5.0%" 0.1000 "10.0%" 0.2500 "25.0%" , nogrid angle(horizontal) labsize(`labsize')) ///
	xlab( .00003 `"".003%" "4,500 Votes""'  0.0001 `"".01%" "15,000""' 0.0003 `"".03%" "45,000""'  0.001 `"".1%" "150,000""' , nogrid angle(horizontal) labsize(`labsize')) ///
	graphr(c(white) lc(white)) ///
	name(multi_detail_`filelabel', replace) ///
	xline(0.000598, lcolor(gs11) lwidth(thin) lpattern(solid) ) /// 0.000598 = 40,865/68,329,141 in 1960 in NJ, IL, MO
	xline(0.000320, lcolor(gs11) lwidth(thin) lpattern(solid) ) ///  0.000320 = 25,579/79,980,515	in 1976 in MI and OH
	xline(0.0006034, lcolor(gs11) lwidth(thin) lpattern(solid) ) /// 0.0006034 = 77744/128,839,000
	xline(0.000276, lcolor(gs11) lwidth(thin) lpattern(solid) ) ///  0.0002760 = 42918/155,484,000
	text(.05 0.000265 " 3 States "  "2020 ", color(gs11) place(w) justification(right) size(`legsize')) ///
	text(.033 0.000320 " 2 States"  " 1976", color(gs11) place(e) justification(left) size(`legsize')) ///
	text(.025 .0006094 " 3 States" " 1960 &" " 2016", color(gs11) place(e) justification(left) size(`legsize')) ///
	legend(order(1 "1 State" 2 "2 States" 3 "3 States") title("Votes Divided Betweeen", size(`legsize')) position(10) col(1) ring(0) region(lwidth(thin)) size(`legsize'))  
	
	graph export "figures`c(dirsep)'FigureA2_`filelabel'.pdf", replace

}
	
	
************************************************
*Reference Tables
************************************************	


//Panel B of Table 2
matrix list RECPCT2STATE2

matrix col1	=RECPCT2STATE2[2..15,1]
matrix col2 = col1*150000000
matrix col3	=RECPCT2STATE2[2..15,3]
matrix col4	=RECPCT2STATE2[2..15,2]
matrix col5	=RECPCT2STATE2[2..15,4]

//binding low resolution in Silver, Gelman due to truncation of source data
forvalues i=1(1)4{
	matrix col5[`i',1]=.
	matrix col3[`i',1]=.
}
matrix PANELB = (col1,col2,col3,col4,col5)
matrix colnames PANELB = percent votesif150M Gelman Geruso Silver
matrix list PANELB

xml_tab PANELB, save("tables`c(dirsep)'Table2b") replace	
	

//Panel C of Table 2
matrix list RECPCT3STATE2

matrix col1	=RECPCT3STATE2[2..15,1]
matrix col2 = col1*150000000
matrix col3	=RECPCT3STATE2[2..15,3]
matrix col4	=RECPCT3STATE2[2..15,2]
matrix col5	=RECPCT3STATE2[2..15,4]

//binding low resolution in Silver, Gelman due to truncation of source data
forvalues i=1(1)4{
	matrix col5[`i',1]=.
	matrix col3[`i',1]=.
}
matrix PANELC = (col1,col2,col3,col4,col5)
matrix colnames PANELC = percent votesif150M Gelman Geruso Silver
matrix list PANELC

xml_tab PANELC, save("tables`c(dirsep)'Table2c") replace	
